SpyneJS

SIX YEARS IN FORTUNE 100 PRODUCTION · OPEN SOURCEThe Behavior-First
Frontend Framework

SpyneJS elevates Behavior to the level of Views,
so structure is defined in the code

The Codebase is the Spec

  • Evolve applications without the guesswork

    SpyneJS precisely defines your application — and reveals exactly where any feature lives. For developers, for agents, for anyone accountable for the system: audit it, trace it, prove what it does.

  • Runs anywhere, connects to your systems

    A SpyneJS application is a complete and coherent unit. Deploy it on any CDN, any cloud, or your own infrastructure. Connect it — full read and write — to the databases, APIs, and services you already run. Nothing to re-platform, nothing to buy.

THE CORE A complete structural language for developers and agents.

Captured Behavior — events and data, wired and declared — unifies the architecture that makes the Codebase the Spec. Every agent, every session, every model reads the same complete definition.

The codebase becomes the spec — it evolves with every change, and developers and agents can read it at the source.

Works with the AI models you already use.

The KB Kit applies your model's fluency to the rules the codebase declares.

The SpyneJS KB Kit ships inside both application templates — versioned with every release, read from source. Working instructions for a framework that models have little to no pre-training on: nothing stale to unlearn, nothing to reconstruct.

npx spyne-cli create-app — then npm start. Same workflow, same tools.

THE PATTERN VBL — View, Behavior, Logic.

Every browser mechanic fits one of three shapes: what renders (View), what moves (Behavior), what decides (Logic). Wired to each other in the codebase, the three shapes give the application its form. Structure is written, never guessed. This is how the Codebase becomes the Spec.

  • Real DOM, declarative Views — each View renders, syncs its content, and nests other Views, every region owned and updated independently. No reconciliation layer. The framework handles rendering through observable chaining and automation.
  • Wiring you can read — every connection between Behavior and Views lives in the code, visible before anything runs.
  • Outside content joins the stream — data, external events, and plugins enter through Channels and run as native behavior.
  • One rule at every scale — the same composition from hello world to the full application.

Hello World — View, Behavior, Logic

The minimal VBL pattern. No hidden lifecycle logic, no implicit control flow — what renders, what moves, and what decides are separated and visible from the start.

Hello World – View, Behavior, Logic

This example shows the minimal, explicit form of the VBL pattern — a ViewStream, a SpyneTrait, and a UI Channel working together with no hidden lifecycle logic or implicit control flow.

Each responsibility is visible and self-contained. What renders, what reacts, and what decides are separated clearly, making the structure easy to follow and reason about as it runs in the browser.

The same relationships shown here — between view, behavior, and logic — are used unchanged as applications grow in complexity, depth, and scope.

Why This Matters:
This example already contains the full architectural model. Nothing is added later to make it scale — complexity accumulates through composition, not through new abstractions. That continuity is what allows applications to remain understandable over time, and what makes SpyneJS a stable foundation for both human and AI-assisted development.

    class MainView extends ViewStream {
      constructor(props = {}) {
        
        // VIEW:          ADD CONTENT
        props.template =  `<h2></h2>
                           ​<button>Click Me</button>`;                           
         
        // BEHAVIOR:      ADD CHANNELS
        props.channels =  ["CHANNEL_UI"];    
        
        // LOGIC:         ADD METHODS
        props.traits =    [HelloWorldTrait];    
        super(props);
      }
    
      // BEHAVIOR: CONNECT EVENTS TO METHODS  
      addActionListeners() {
        return [["CHANNEL_UI_CLICK_EVENT", "hw$greet"]];
      }
    
      // BEHAVIOR: SEND LOCAL EVENTS
      broadcastEvents() {
        return [["button", "click"]];
      }
    
      // RENDER HOOK
      onRendered() {
        this.hw$greet();
      }
    }
    
    new MainView().appendToDom(document.body);
  •   class HelloWorldTrait extends SpyneTrait {
        constructor(context) {
        
          // LOGIC: Binds pure functions
          super(context, "hw$");
        }
      
        // Trait method that rotates the array
        static hw$greet() {
          // Initialize the greetings array once, 
          storing it in props
          if (!this.props.greetings) {
            this.props.greetings = [
              "Hello World", "Hola Mundo", "Bonjour le monde", 
              "Hallo Welt", "こんにちは世界", "你好,世界", 
              "안녕하세요 월드", "Привіт, світе", "مرحبا بالعالم", 
              "Olá Mundo", "Ciao Mondo"
            ];
          }
      
          // Remove the first item
          const currentGreeting = this.props.greetings.shift();
          // Update the UI
          this.props.el$("h2").el.innerText = currentGreeting;
          // Re-insert the item at the end to cycle
          this.props.greetings.push(currentGreeting);
        }
      }
            

The same relationships shown here scale unchanged as the application grows in complexity, depth, and scope.

GET STARTED Start with a complete application.

The Application Shell is a running SpyneJS application, pre-wired: an app model, full configuration, and the standard plugins installed.

  • CMS

    Author content — and exchange data with AI — where the application runs. Local JSON files are the database: versionable with the repo, no external service.

  • Behavior Console

    Every channel, every event, every payload — streaming live as the application runs. The structure describes itself in real time.

  • Spyne-CLI

    Scaffold, serve, and build from the command line. create-app builds the initial app from your prompt, and can generate VBL code as your app evolves.

Every setting you choose is captured as structured data — routes, window behavior, runtime flags — declared and embedded in what you download. The KB Kit is already inside: your AI tools read the current Knowledge Base from the first prompt.

Keep the editor, the agents, and the workflow you have. The Shell adds the application.

Start with an Application Shell →

EXTENSIONS Expand your app

A SpyneJS plugin is a complete SpyneJS application — the same VBL pattern, plus hooks for integration. It connects to the host's single configuration and behaves like everything else in the host.

The web is wider than any framework — services, libraries, design systems, running products. Plugins are how SpyneJS reaches it: external behavior enters through Channels and joins the stream; nothing reaches farther than its declared connections.

The same shape travels the other way. Components, themes, and working features move between applications as plugins — VBL content any host can register.

Plugins begin by extending SpynePlugin — one class, one level, the same composition rule as everything else. Start from the plugin template, wire a channel, and the application can hear it.

CMS and the Behavior Console enter this way too — they ship with the Application Shell.

There's no curated plugin portal yet — plugins move through GitHub and npm.

The catalog is young. The architecture is not.

OPEN SOURCE SpyneJS is open source and free to use.

Everything on this page is available today. All of it is beta — 1.0 comes when the community has vetted it, not before.

npx spyne-cli create-app